#include "tcp.h"
#include "netif.h"
#include "etharp.h"
#include "ip_addr.h"
uint8_t jj=0;
/*
****tcp校验和计算
*/


uint16_t tcp_checksum(struct netif *netif,uint8_t *buff)
{
  
  uint16_t tcp_sum=0;
  typedef struct{
    uint32_t  src_ip;
    uint32_t  des_ip;
    uint8_t  mbz;                //置空
    uint8_t  protocol;           //协议类型
    uint16_t len1;                //tcp长度
  }psd_header;  //伪首部
  uint8_t *temp=mymalloc(SRAM_IN,netif->ip_datalen+sizeof(psd_header));
  psd_header   *tcp_sub_hdr=(psd_header   *)temp;
  tcp_sub_hdr->des_ip=htonl(netif->remotip_addr.addr);
  tcp_sub_hdr->src_ip=htonl(netif->lacotip_addr.addr);     
  tcp_sub_hdr->mbz=0;
  tcp_sub_hdr->protocol=IP_PROTO_TCP;
  tcp_sub_hdr->len1=htons(netif->ip_datalen);
  //校验数据
  memcpy(temp+sizeof(psd_header),buff,
         netif->ip_datalen);
  tcp_sum=ip_checksum(temp,netif->ip_datalen+sizeof(psd_header)); 
  myfree(SRAM_IN,temp);
  return tcp_sum;
}
/*
***PCB分配内存
*/
struct tcp_pcb*
tcp_new(void){
  struct tcp_pcb *pcb;
  pcb=(struct tcp_pcb*)mymalloc(SRAM_IN,sizeof(struct tcp_pcb));
  if(pcb==NULL)
  {
      memset(pcb,0,sizeof(struct tcp_pcb));
      return NULL;
  }
  return pcb;
}
/*
**为PCB绑定属性
**如无IP地址和端口，填0；
*/
uint8_t
tcp_bind(struct tcp_pcb *pcb,ip_addr_t *ipaddr,uint16_t port){
  
  if(pcb==NULL)
    return NULL; //无控制块配置
  ip_addr_set(&pcb->local_ip,ipaddr);
  pcb->local_port=port; 
  return 1;//绑定完成
}
/*
***为PCB块注册读取数据回调函数
*/
void
tcp_recv(struct tcp_pcb *pcb,tcp_recv_fn recv){
    pcb->recv=recv;
}
/*
***TCP接收数据处理
*/
void
tcp_input(struct netif *netif,struct pbuf *p){
  Pack_tcp_hdr   *tcphdr;
  struct netif *lnetif;
  uint16_t port=0;
  uint16_t tcpsum=0;
  uint8_t  flags;
  tcphdr =(Pack_tcp_hdr *)((uint8_t *)p->payload+p->hdr_len);
/*遍历链表*/  
for(lnetif=netif;lnetif !=NULL;lnetif=lnetif->next){  

  //取出校验和
  tcpsum =htons(tcphdr->chksum);
  //置零
  tcphdr->chksum=0;  
  if(tcpsum !=tcp_checksum(lnetif,((uint8_t *)p->payload+p->hdr_len)))
            goto tcp_err_goto;
  /*目的端口*/
  port=htons(tcphdr->dest);
  /*标志位对应*/
  flags=TCPH_FLAGS(tcphdr);
  
 
    if(port==lnetif->tpcb->local_port){
      /*暂时只添加需要的，有需求自己添加，case*/
      /*保存远端端口*/ 
      lnetif->tpcb->remote_port=htons(tcphdr->src);
      /*seq*/
      lnetif->tpcb->rcv_nxt    =htonl(tcphdr->seqno);
      /*ACK*/
      lnetif->tpcb->rcv_sqe    =htonl(tcphdr->ackno);
      /*tcphdr*/
      lnetif->tpcb->tcp_hdrlen =TCPH_HDRLEN(tcphdr);
      /*tcp数据*/
      
      switch(flags){
      case TF_FLAGS_SYN:
          tcp_ack_smmp(lnetif,p,&lnetif->remotip_addr);
          break;
      case TF_SMMP_ACK:         
          lnetif->tpcb->recv(NULL,lnetif->tpcb,p,
                             &lnetif->remotip_addr,    
                            lnetif->tpcb->remote_port);
          /**/  
          tcp_smpprev_ack(lnetif,p,&lnetif->remotip_addr);           
        break;
      case TF_FLAGS_ACK|TF_FLAGS_SYN:
        break;
      case TF_FLAGS_RST:
        break;
      case TF_FLAGS_FIN:
        break;
      default:
        break;
      }
     break;
    }
  }
tcp_err_goto:
p->payload=myfree(SRAM_IN,p->payload);
p=(struct pbuf *)myfree(SRAM_IN,p);

}
/*
**TCP输出函数,从传输层送至数据链路层
*/
void 
tcp_output(Pack_tcp_hdr *tcp_hdr,struct netif *netif,struct pbuf *p,
           ip_addr_t *addr)
{
  Pack_tcp_hdr   *tcphdr;
  
  struct pbuf *pbuf;
  tcphdr=tcp_hdr;
    /*源端口*/
  tcphdr->src =htons(netif->tpcb->local_port);
    /*目的端口*/
  tcphdr->dest=htons(netif->tpcb->remote_port);
  
  tcphdr->wnd=htons(546);
  tcphdr->urgp=0;//紧急指针
  
  tcphdr->chksum=tcp_checksum(netif,(uint8_t *)tcphdr);
    /*通知上层数据处理*/
  netif->flags=IP_PROTO_TCP; 
    /*释放已经处理好数据的内存*/
  myfree(SRAM_IN,p->payload);
  /*申请内存*/
  pbuf=mymalloc(SRAM_IN,sizeof(struct pbuf));
  /*数据长度+报文，申请内存用到*/
  //应答无数据
  pbuf->len=p->hdr_len+(netif->tpcb->tcp_hdrlen*4); 
  /*申请内存*/
  pbuf->payload=mymalloc(SRAM_IN,pbuf->len);
  
  pbuf->next=NULL;
  if(pbuf !=NULL){
    /*修改为数据长度*/
    pbuf->len=0;  
    /*报文长度*/
    pbuf->hdr_len =p->hdr_len+(netif->tpcb->tcp_hdrlen*4);
    /*整包长度*/
    pbuf->data_len =pbuf->len+pbuf->hdr_len; 
     
    memcpy((uint8_t *)pbuf->payload+p->hdr_len,tcphdr,
           (netif->tpcb->tcp_hdrlen*4));
    /*传至Ip层*/
    myfree(SRAM_IN,p);
    ip_output(netif,pbuf,addr);
  }
}
/*
***TCP连接，
***这里只写了TCP服务器应答客服端的请求链接，
***
*/
void 
tcp_ack_smmp(struct netif *netif,struct pbuf *p,ip_addr_t *addr)
{
  Pack_tcp_hdr   tcphdr;
  /*seq*/
  tcphdr.seqno=htonl(netif->tpcb->rcv_sqe);//???
  /*ack*/
  tcphdr.ackno=htonl(netif->tpcb->rcv_nxt+1);
  /*首部长度*/
  TCPH_HDRLEN_SET(&tcphdr,0x0006);
  /*flags*/
  tcphdr._hdrlen_rsvd_flags|=htons(TF_FLAGS_ACK|TF_FLAGS_SYN);
  /*保存TCP首部长度*/
  netif->tpcb->tcp_hdrlen=6;
  
  tcp_output(&tcphdr,netif,p,addr);
}
/*
***TCP连接，
***，
***
*/
void
tcp_smpprev_ack(struct netif *netif,struct pbuf *p,ip_addr_t *addr)
{
  Pack_tcp_hdr   tcphdr;
  /*seq*/
  tcphdr.seqno=htonl(netif->tpcb->rcv_sqe);//???
  /*ack*/
  tcphdr.ackno=htonl(netif->tpcb->rcv_nxt);
    /*首部长度*/
  TCPH_HDRLEN_SET(&tcphdr,0x0005);
  /*flags*/
  tcphdr._hdrlen_rsvd_flags|=htons(TF_FLAGS_ACK);
    /*保存TCP首部长度*/
  netif->tpcb->tcp_hdrlen=5;
  
  tcp_output(&tcphdr,netif,p,addr);
}
